//! MajorSystem class definition

#include "include/MajorSystem.h"
#include <assert.h>

#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QRegExp>

#include <sstream>

// http://en.wikipedia.org/wiki/Mnemonic_major_system

MajorSystemWord::MajorSystemWord(QString word)
{
	m_word = word.toLower();
	buildNum();
}

bool MajorSystemWord::operator==(const QString& num)
{
	return num == m_numStr;
}

bool MajorSystemWord::operator<(const MajorSystemWord& rOther) const
{
	return m_word < rOther.m_word;
}

unsigned int MajorSystemWord::getNumMajorSounds() const
{
	return m_numStr.size();
}

const QString& MajorSystemWord::getWord() const
{
	return m_word;
}

const QString& MajorSystemWord::getNum() const
{
	return m_numStr;
}

bool MajorSystemWord::testWord(const QString& word, const QString& number)
{
	MajorSystemWord w(word);
	if (w.getNum() != number)
	{
		qDebug() << word + " was not equals to:";
		qDebug() << number + " - but equals to:";
		qDebug() << w.getNum();
		return false;
	}
	return true;
}

void MajorSystemWord::MajorSystemWordTest()
{
	assert(testWord("enough", "28"));
	assert(testWord("missile", "305"));
	assert(testWord("Hindquarters", "2174140"));
	assert(testWord("MeTeoRTaiLPiNK", "31415927"));
	assert(testWord("thequickbrownfoxjumpedoverthelazydog", "17794287063918415017"));
	assert(testWord("might", "31"));
	assert(testWord("phrase", "840"));

	// these two tests fail, really ought to use bison
//	assert(testWord("rigging", "476"));
//	assert(testWord("Youmightusethisphraseifyougetstuckwhenjustbeginningbutpleasedonttrytolearnthecodethisway","31010840871017260197269195012114154217110"));
}

QString	 MajorSystemWord::nextLetter(QString::const_iterator it)
{
	if (it + 1 != m_wordWrk.end())
		return *(it + 1);
	else return "";
}

QString	 MajorSystemWord::previousLetter(QString::const_iterator it)
{
	if (it != m_wordWrk.begin())
		return *(it - 1);
	else return "";
}

void MajorSystemWord::buildNum()
{
	QString word = m_word;
	word.replace(QRegExp("ght"), "t");
	word.replace(QRegExp("ph"), "f");
	word.replace(QRegExp("get"), "kt");

	m_wordWrk = "";
	// discard doubled / tripled etc. letters
	// apart for those that matter (like c)
	// i.e succion (0762)
	if (word.size() != 0)
	{
		QString lastLetter;

		for (QString::const_iterator it = word.begin(); it != word.end(); it++)
		{
			QString letter = *it;
			if (letter != lastLetter or (letter == "c" or letter == "g"))
				m_wordWrk.append(*it);
			lastLetter = *it;
		}
	}

	// string parsing
	for (QString::const_iterator it = m_wordWrk.begin(); it != m_wordWrk.end(); it++)
	{
		QString letter = *it;
		if ((letter == "s" && nextLetter(it) != "h") || letter == "z")
			m_numStr.append("0");
		else if (letter == "c" && (nextLetter(it) == "e" || nextLetter(it) == "i" || nextLetter(it) == "y"))
		{
			m_numStr.append("0");
			it++;
		}
		else if (letter == "d" or letter == "t")
			m_numStr.append("1");
		else if (letter == "n" and nextLetter(it) != "g")
			m_numStr.append("2");
		else if (letter == "m")
			m_numStr.append("3");
		else if (letter == "r")
			m_numStr.append("4");
		else if (letter == "l")
			m_numStr.append("5");
		// 6
		else if (((	letter == "s" or letter == "c") and nextLetter(it) == "h")  or letter == "j" ||
				 (letter == "g" and (nextLetter(it) == "e" or nextLetter(it) == "i" or nextLetter(it) == "y")))
		{
			m_numStr.append("6");
		}
		// 7
		else if ((letter == "g" and nextLetter(it) != "h") or (letter == "k" or letter == "q" or letter == "c"))
		{
			m_numStr.append("7");
			if (letter == "c" and nextLetter(it) == "k")
				it++;
		}
		// 8
		else if (letter == "f" or letter == "v" or (letter == "g" and nextLetter(it) == "h"))
			m_numStr.append("8");
		else if (letter == "b" or letter == "p")
			m_numStr.append("9");
		else if (letter == "x")
			m_numStr.append("70");
	}
}
